﻿#include "tcpserver.h"

vector<clientData *> *clientArray; // 用户数据数组
pthread_mutex_t mutex;             // 互斥锁

TcpServer::TcpServer()
{
    mutex = PTHREAD_MUTEX_INITIALIZER; // 初始化线程互斥锁
    clientArray = new vector<clientData *>;
    initSocket();
}

int TcpServer::initSocket()
{
    // 申请网络套接字文件
    if ((serverFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket");
        return -1;
    }
    cout << "申请IPV4的TCP协议的网络套接字成功" << endl;
    int sw = 1;
    // 设置套接字属性
    setsockopt(serverFd, SOL_SOCKET, SO_REUSEADDR, &sw, sizeof(int)); // 设置套接字可以地址复用

    // 声明套接字sockaddr_in结构体变量，表示服务器
    struct sockaddr_in serverAddr;
    memset(&serverAddr, 0, sizeof(struct sockaddr_in));
    // 初始化服务器端的套接字，并用htons和htonl将端口和地址转成网络字节序
    serverAddr.sin_family = AF_INET;          // 指定协议是使用IPV4的协议
    serverAddr.sin_port = htons(SERVER_PORT); // 指定端口号,htons用短整型的方式转化为网络字节序
    // ip可是是本服务器的ip，也可以用宏INADDR_ANY代替，代表0.0.0.0，表明所有网卡地址
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(serverFd, (struct sockaddr *)&serverAddr, sizeof(struct sockaddr_in)) < 0)
    {
        perror("connect");
        return -2;
    }
    cout << "绑定IP和端口到申请的网络套接字成功" << endl;

    // 设置网络容量，开启网络监听
    if (listen(serverFd, LIMIT_CONNECT) < 0)
    {
        perror("listen");
        return -3;
    }
    cout << "开启网络监听成功" << endl;
    return 0;
}

clientData *TcpServer::listenLink()
{
    struct sockaddr_in clientAddr;
    socklen_t addrLen = sizeof(struct sockaddr_in);
    int clientFd;

    cout << "serverFd=" << serverFd << endl;

    // 等待客户端连接,获取客户端信息
    clientFd = accept(serverFd, (struct sockaddr *)&clientAddr, &addrLen);
    if (clientFd < 0)
    {
        perror("accept");
        return NULL;
    }

    // 客户端信息保存
    clientData *cd = new clientData;
    cd->clientFd = clientFd;
    cd->ip = inet_ntoa(clientAddr.sin_addr);
    cd->port = htons(clientAddr.sin_port);
    cout << "客户端连接成功,IP = " << cd->ip << ",port = " << cd->port << ",fd = " << cd->clientFd << endl;

    return cd;
}

void TcpServer::connectClient()
{
    while (true)
    {
        clientData *cd = listenLink();
        if (clientArray->size() > LIMIT_CONNECT)
        {
            continue;
        }
        pthread_mutex_lock(&mutex); // 加锁
        clientArray->push_back(cd);
        pthread_mutex_unlock(&mutex); // 解锁
        TcpSession *ts = new TcpSession(cd);
        ts->start();
        // ts->run();
        //        cd->ts = &ts;
    }
}
